package com.beemans.corekit.integration.admob;

import android.app.Activity;
import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.gms.ads.AdError;
import com.google.android.gms.ads.FullScreenContentCallback;
import com.google.android.gms.ads.LoadAdError;
import com.google.android.gms.ads.ResponseInfo;
import com.google.android.gms.ads.admanager.AdManagerAdRequest;
import com.google.android.gms.ads.rewarded.RewardedAd;
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;

public class AbRewardAdWrapper {
    @NonNull
    private final String placementId;
    @Nullable
    private RewardedAd mRewardedAd = null;
    @Nullable
    private AbRewardAdEventListener mEventListener;
    @Nullable
    private AbAdNetworkListener mNetworkListener;

    private boolean isLoadingAd = false;
    private boolean isShowingAd = false;
    private boolean isAdPreviewed = false;

    public AbRewardAdWrapper(@NonNull String placementId) {
        this.placementId = placementId;
    }

    @NonNull
    public String getPlacementId() {
        return placementId;
    }

    public boolean isAdvertReady() {
        return mRewardedAd != null && !isAdPreviewed;
    }

    public boolean isAdvertLoading() {
        return isLoadingAd;
    }

    public boolean isAdvertShowing() {
        return isShowingAd;
    }

    public void loadAd(
            @NonNull Context context,
            @NonNull AbAdNetworkListener networkListener
    ) {
        isLoadingAd = true;
        mNetworkListener = networkListener;

        AbAdvertLoadManager.getInstance().updateRewardLoadingList(this, false);

        try {
            final AdManagerAdRequest request = new AdManagerAdRequest.Builder().build();
            RewardedAd.load(context, placementId, request, new RewardedAdLoadCallback() {
                @Override
                public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
                    isLoadingAd = false;
                    mRewardedAd = rewardedAd;

                    onAdvertLoadComplete();
                    AbAdvertLoadManager.getInstance().updateRewardReadyList(AbRewardAdWrapper.this, false);

                    rewardedAd.setOnPaidEventListener(adValue -> {
                        if (mEventListener != null) {
                            mEventListener.onAdPaidEvent(getResponseInfo(), adValue);
                        }
                    });

                    if (mNetworkListener != null) {
                        mNetworkListener.onAdLoaded();
                    }
                }

                @Override
                public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
                    isLoadingAd = false;

                    onAdvertLoadComplete();
                    handleAdFailedToLoad(mNetworkListener, loadAdError.toString());
                }
            });
        } catch (Throwable throwable) {
            isLoadingAd = false;
            mNetworkListener = null;

            onAdvertLoadComplete();
            handleAdFailedToLoad(networkListener, throwable.getMessage());
        }
    }

    public void showAd(
            @NonNull Activity activity,
            @NonNull AbRewardAdEventListener eventListener
    ) {
        AbAdvertLoadManager.getInstance().updateRewardReadyList(this, true);

        if (mRewardedAd == null) {
            handleAdDisplayFailed(eventListener, "");
            return;
        }

        isAdPreviewed = true;
        isShowingAd = true;
        mEventListener = eventListener;

        mRewardedAd.setFullScreenContentCallback(new FullScreenContentCallback() {
            @Override
            public void onAdImpression() {
                if (mEventListener != null) {
                    mEventListener.onAdImpression(getResponseInfo());
                }
            }

            @Override
            public void onAdClicked() {
                if (mEventListener != null) {
                    mEventListener.onAdClicked(getResponseInfo());
                }
            }

            @Override
            public void onAdDismissedFullScreenContent() {
                isShowingAd = false;

                if (mEventListener != null) {
                    mEventListener.onAdClosed(getResponseInfo());
                }

                mRewardedAd = null;
            }

            @Override
            public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
                isShowingAd = false;
                mRewardedAd = null;

                handleAdDisplayFailed(mEventListener, adError.toString());
            }

            @Override
            public void onAdShowedFullScreenContent() {
            }
        });

        try {
            mRewardedAd.show(activity, rewardItem -> {
                if (mEventListener != null) {
                    mEventListener.onUserEarnedReward(rewardItem);
                }
            });
        } catch (Throwable throwable) {
            isAdPreviewed = false;
            isShowingAd = false;
            mEventListener = null;

            handleAdDisplayFailed(eventListener, throwable.getMessage());
        }
    }

    public void destroy() {
        mNetworkListener = null;
        mEventListener = null;

        if (isAdPreviewed && mRewardedAd != null) {
            mRewardedAd = null;
        }
    }

    @Nullable
    private ResponseInfo getResponseInfo() {
        return mRewardedAd != null ? mRewardedAd.getResponseInfo() : null;
    }

    private void handleAdDisplayFailed(
            @Nullable AbAdEventListener eventListener,
            @Nullable String adError
    ) {
        if (eventListener != null) {
            eventListener.onAdDisplayFailed(adError);
        }
    }

    private void handleAdFailedToLoad(
            @Nullable AbAdNetworkListener networkListener,
            @Nullable String loadAdError
    ) {
        if (networkListener != null) {
            networkListener.onAdFailedToLoad(loadAdError);
        }
    }

    private void onAdvertLoadComplete() {
        AbAdvertLoadManager.getInstance().updateRewardLoadingList(this, true);
    }
}